/*
*******************************************************************************
*                              (c) Copyright HighSun Techonology Company
*                                           All Rights Reserved
*
* File    : freq_cal.c
* By      : HuangXi
* Version : V0.1
* Datetime: 2012-02-22 PM 20:36
* Description: Function define for frequency test
*******************************************************************************
*/
#include <includes.h>

/* For save the frequency value */
typedef struct _freq_cal
{
    Uint32   Tst_head;
    Uint32   Tst_tail;
    Uint32   Tst_last_head;
    float64  freq;
    Uint16   vol;
    Uint32   freq_counter;
    Uint32   prev_freq_counter;
}FREQ_CAL;


 static FREQ_CAL freq_cal;




/*********************** Function Declare *************************/
interrupt void cap1_isr(void);


/* Initialize the CAP1 */
void cap1_init(void)
{
    DINT;
    EALLOW;


    /* Initialize the structure */
    freq_cal.Tst_head = 0;
    freq_cal.Tst_tail = 0;
    freq_cal.freq     = 50;
    freq_cal.Tst_last_head     = 0;
    freq_cal.freq_counter      = 0;
    freq_cal.prev_freq_counter = 0;
    

    /* Enable pull-up for GPIO24 (CAP1) */
	GpioCtrlRegs.GPAPUD.bit.GPIO24   = 0;    

    /* Asynch input GPIO24 (CAP1) */
    GpioCtrlRegs.GPAQSEL2.bit.GPIO24 = 3;  

    /* Configure GPIO24 for CAP1 operation */
    GpioCtrlRegs.GPAMUX2.bit.GPIO24  = 1;   

    

    /* Stop the counter */
    ECap1Regs.ECCTL2.bit.TSCTRSTOP   = EC_STOP;
    ECap1Regs.ECEINT.all             = EC_DISABLE;

    /* Config the pherial registers */
    ECap1Regs.ECCTL1.bit.CAP1POL     = EC_RISING;
    ECap1Regs.ECCTL1.bit.CTRRST1     = EC_ABS_MODE;
    ECap1Regs.ECCTL1.bit.PRESCALE    = EC_BYPASS;
    ECap1Regs.ECCTL2.bit.CAP_APWM    = EC_CAP_MODE;
    ECap1Regs.ECCTL2.bit.CONT_ONESHT = EC_CONTINUOUS;
    ECap1Regs.ECCTL2.bit.SYNCO_SEL   = EC_SYNCO_DIS;
    ECap1Regs.ECCTL2.bit.SYNCI_EN    = EC_DISABLE;
    ECap1Regs.ECCTL2.bit.STOP_WRAP   = WRAP_CAP1; 
    ECap1Regs.ECCTL1.bit.CAPLDEN     = EC_ENABLE;
    ECap1Regs.ECCTL1.bit.FREE_SOFT   = FREE_SOFT_MODE;


    /* Enable irq and start counter */
    ECap1Regs.ECCLR.all              = 0xFF;
    PieVectTable.ECAP1_INT           = &cap1_isr;

    /* Enable the irq of PIE level */
    PieCtrlRegs.PIEIER4.bit.INTx1    = DEF_ENABLE;

    /* Enable the irq of CPU level */
    IER |= M_INT4;
    
    ECap1Regs.ECEINT.bit.CEVT1       = EC_ENABLE;
    EDIS;
    EINT;
    
    ECap1Regs.ECCTL2.bit.TSCTRSTOP   = EC_RUN;


}


/* ISR for CAP1 */
interrupt void cap1_isr(void)
{
    
    Uint32 clocks   = 0;
    Uint32 tcnt_max = 0xFFFFFFFFUL;


    

    /* Trigger AD Sample */
    start_ad_sample(freq_cal.freq, SAMPLE_POINTS);
    
    /* Get the clocks */
    freq_cal.Tst_tail = ECap1Regs.CAP1;

    /* Get the clocks via interval of pulse*/
    if (freq_cal.Tst_tail > freq_cal.Tst_head)
    {
        clocks = (freq_cal.Tst_tail - freq_cal.Tst_head);
    }else{
        clocks = (Uint32)((tcnt_max - freq_cal.Tst_head) + freq_cal.Tst_tail);
    }

    
    /* Calculation the frequency */
    if (clocks != 0)
    {
        freq_cal.freq     = ((float64)(DSP28_PLLCR * OSC_FREQ) / (float64)DSP28_DIVSEL )/ (float64)clocks;
        freq_cal.Tst_last_head = freq_cal.Tst_head;
        freq_cal.Tst_head = freq_cal.Tst_tail;
    }

    /* freq counter increment mean's Freq active */
    freq_cal.freq_counter %= 0xFF;
    freq_cal.freq_counter++;
    
    /* Clear irq flag of CAP1 */
    ECap1Regs.ECCLR.bit.CEVT1 = 1;
    ECap1Regs.ECCLR.bit.INT   = 1;
    PieCtrlRegs.PIEACK.all    = PIEACK_GROUP4;

}


/* Get the frequency */
Uint32 get_freq(void)
{
    return (Uint32)(freq_cal.freq*1000);
}


/* For debug */
Uint32 get_last_head(void)
{
    return freq_cal.Tst_last_head;
}


/* For debug */
Uint32 get_head(void)
{
    return freq_cal.Tst_head;
}

Uint32 get_prev_freq_cal(void)
{
    return freq_cal.prev_freq_counter;
}

void set_prev_freq_cal(Uint32 freq_counter)
{
    freq_cal.prev_freq_counter = freq_counter;
}


Uint32 get_freq_cal(void)
{
    return freq_cal.freq_counter;
}

